#include <SDL2/SDL.h>
#include <iostream>

// 按键枚举值
enum KeyPressSurfaces
{
    KEY_PRESS_SURFACE_DEFAULT,
    KEY_PRESS_SURFACE_UP,
    KEY_PRESS_SURFACE_DOWN,
    KEY_PRESS_SURFACE_LEFT,
    KEY_PRESS_SURFACE_RIGHT,
    KEY_PRESS_SURFACE_TOTAL
};

// sdl初始化并创建窗口
bool init();

// 加载图片
bool loadMedia();

// 关闭sdl并释放资源
void close();

// 加载单个图片
SDL_Surface* loadSurface( std::string path );

// 渲染的窗口
SDL_Window * gWindow = nullptr;

// 窗口表面
SDL_Surface * gScreenSurface = nullptr;

// 按键对应的图像,数组有5个值
SDL_Surface* gKeyPressSurfaces[ KEY_PRESS_SURFACE_TOTAL ];

// 当前展示的图片
SDL_Surface * gCurrentSurface = nullptr;

const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;

bool init()
{
     //Initialization flag
    bool success = true;

    //Initialize SDL
    if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
    {
        char str[1024];
        sprintf(str, "SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
        std::cout << str << std::endl;
        success = false;
    }
    else
    {
        //Create window
        gWindow = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
        if( gWindow == nullptr )
        {
            char str[1024];
            sprintf(str, "Window could not be created! SDL_Error: %s\n", SDL_GetError());
            std::cout << str << std::endl;
            success = false;
        }
        else
        {
            //Get window surface
            gScreenSurface = SDL_GetWindowSurface( gWindow );
        }
    }

    return success;
}

SDL_Surface* loadSurface( std::string path )
{
    //Load image at specified path
    SDL_Surface* loadedSurface = SDL_LoadBMP( path.c_str() );
    if( loadedSurface == nullptr )
    {
        char str[1024];
        sprintf(str, "Unable to load image %s! SDL Error: %s\n", path.c_str(), SDL_GetError());
        std::cout << str << std::endl;
    }

    return loadedSurface;
}

bool loadMedia()
{
    //Loading success flag
    bool success = true;

    //Load default surface
    gKeyPressSurfaces[ KEY_PRESS_SURFACE_DEFAULT ] = loadSurface( "press.bmp" );
    if( gKeyPressSurfaces[ KEY_PRESS_SURFACE_DEFAULT ] == nullptr )
    {
        std::cout << "Failed to load default image!" << std::endl;
        success = false;
    }

    //Load up surface
    gKeyPressSurfaces[ KEY_PRESS_SURFACE_UP ] = loadSurface( "up.bmp" );
    if( gKeyPressSurfaces[ KEY_PRESS_SURFACE_UP ] == nullptr )
    {
        std::cout << "Failed to load up image!" << std::endl;
        success = false;
    }

    //Load down surface
    gKeyPressSurfaces[ KEY_PRESS_SURFACE_DOWN ] = loadSurface( "down.bmp" );
    if( gKeyPressSurfaces[ KEY_PRESS_SURFACE_DOWN ] == nullptr )
    {
        std::cout << "Failed to load down image!" << std::endl;
        success = false;
    }

    //Load left surface
    gKeyPressSurfaces[ KEY_PRESS_SURFACE_LEFT ] = loadSurface( "left.bmp" );
    if( gKeyPressSurfaces[ KEY_PRESS_SURFACE_LEFT ] == nullptr )
    {
        std::cout << "Failed to load left image!" << std::endl;
        success = false;
    }

    //Load right surface
    gKeyPressSurfaces[ KEY_PRESS_SURFACE_RIGHT ] = loadSurface( "right.bmp" );
    if( gKeyPressSurfaces[ KEY_PRESS_SURFACE_RIGHT ] == nullptr )
    {
        std::cout << "Failed to load right image!" << std::endl;
        success = false;
    }

    return success;
}

void close()
{
    // 释放资源
    // delete[] gKeyPressSurfaces;
    for (int i = 0; i < KEY_PRESS_SURFACE_TOTAL; i++)
    {
        SDL_FreeSurface(gKeyPressSurfaces[i]);
        gKeyPressSurfaces[i] = nullptr;
    }
    

    //Deallocate surface
    SDL_FreeSurface( gCurrentSurface );
    gCurrentSurface = nullptr;

    //Destroy window
    SDL_DestroyWindow( gWindow );
    gWindow = nullptr;

    //Quit SDL subsystems
    SDL_Quit();
}


int main( int argc, char* args[] )
{
    //Start up SDL and create window
    if( !init() )
    {
        std::cout << "Failed to initialize!" << std::endl;
    }
    else
    {
        //Load media
        if( !loadMedia() )
        {
            std::cout << "Failed to load media!" << std::endl;
        }
        else
        {
            //Hack to get window to stay up
            SDL_Event e; 
            bool quit = false; 
            //设置默认展示的图像
            gCurrentSurface = gKeyPressSurfaces[ KEY_PRESS_SURFACE_DEFAULT ];

            //While application is running
            while( !quit )
            {
                //Handle events on queue
                while( SDL_PollEvent( &e ) != 0 )
                {
                    //User requests quit
                    if( e.type == SDL_QUIT )
                    {
                        quit = true;
                    }
                    //User presses a key
                    else if( e.type == SDL_KEYDOWN )
                    {
                        //Select surfaces based on key press
                        // SDL 事件内部有一个 SDL 键盘事件，其中包含按键事件的信息。其中的 SDL Keysym 包含按下按键的相关信息。该 Keysym 包含 SDL 键码，可识别按下的键
                        switch( e.key.keysym.sym )
                        {
                            // 识别的是键盘的上下左右四个方向按键
                            case SDLK_UP:   
                            gCurrentSurface = gKeyPressSurfaces[ KEY_PRESS_SURFACE_UP ];
                            break;

                            case SDLK_DOWN:
                            gCurrentSurface = gKeyPressSurfaces[ KEY_PRESS_SURFACE_DOWN ];
                            break;

                            case SDLK_LEFT:
                            gCurrentSurface = gKeyPressSurfaces[ KEY_PRESS_SURFACE_LEFT ];
                            break;

                            case SDLK_RIGHT:
                            gCurrentSurface = gKeyPressSurfaces[ KEY_PRESS_SURFACE_RIGHT ];
                            break;

                            default:
                            gCurrentSurface = gKeyPressSurfaces[ KEY_PRESS_SURFACE_DEFAULT ];
                            break;
                        }
                    }
                }
                //Apply the current image
                SDL_BlitSurface( gCurrentSurface, NULL, gScreenSurface, NULL );
            
                //Update the surface
                SDL_UpdateWindowSurface( gWindow );
            }
        }
    }

    //Free resources and close SDL
    close();

    return 0;
}


